package com.zhdl.network.duplexprotocol;

import cn.hutool.core.util.HexUtil;
import com.project.command.faq.event.client.MessageInDataSource;
import com.project.common.util.ByteHelper;
import com.project.network.client.SocketMessageInEmitNext;
import com.zhdl.common.eventbus.center.EventBusCenter;
import com.zhdl.hardware.plc.siemens.entity.SiemensReceiveData;
import com.zhdl.network.modbustcp.dto.ModbusPacket;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.tio.core.ChannelContext;
import org.tio.core.TioConfig;
import org.tio.core.exception.TioDecodeException;
import org.tio.core.intf.Packet;
import org.tio.server.intf.TioServerHandler;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Data
public class CunstomTcpServerHandler implements TioServerHandler, SocketMessageInEmitNext {
    /**
     * 监听在服务端口
     */
    private String port;

    /**
     * 监听在服务ip
     */
    private String ip;

    private String protocols;

    private MessageInDataSource message;
//
//    @Resource
//    private TotalParameterCoreService totalParameterCoreService;


    public CunstomTcpServerHandler(String ip, String port, String protocols, MessageInDataSource message) {
        this.ip = ip;
        this.port = port;
        this.protocols = protocols;
        this.message = message;
    }


    /**
     * 解包逻辑，支持粘包拆包，只进行初步的解包，只按协议结构解析，不解析具体的数据单元
     *
     * @param buffer
     * @param limit          结束标记下标，表示进行下一个读写操作时的（最大）结束位置；小于等于ByteBuffer容量
     * @param position       当前读写的位置index,ByteBuffer的position，不一定是0
     * @param readableLength 可读的数据长度,ByteBuffer参与本次解码的有效数据（= limit - position）
     * @param channelContext
     * @return 返回null表示拼包失败
     * @throws TioDecodeException
     */
    @Override
    public Packet decode(ByteBuffer buffer, int limit, int position, int readableLength, ChannelContext channelContext) throws TioDecodeException {
        try {

            log.debug("---- decode ---");

            log.debug(String.format("接收数据 position: %s limit: %s capacity: %s", buffer.position(), buffer.limit(), buffer.capacity()));
            // log.debug(ByteHelper.byteToString(buffer.array()));

            ModbusPacket outpkt = new ModbusPacket();
            byte[] bytes = new byte[readableLength];
            buffer.get(bytes);
            outpkt.setUnitBuff(bytes);
            outpkt.setFullBuff(bytes);
            buffer.compact();
            buffer.flip();
            return outpkt;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }


    /**
     * 编码处理，组装发送数据包，在外部已经组装好了要发送的完整数据包，所以这里不再加工，直接发送就行。
     *
     * @param packet
     * @param tioConfig
     * @param channelContext
     * @return
     */
    @Override
    public ByteBuffer encode(Packet packet, TioConfig tioConfig, ChannelContext channelContext) {
        try {
            ModbusPacket pkt = (ModbusPacket) packet;
            byte[] sendBuff = pkt.getFullBuff();
            log.debug("发送数据：{}", ByteHelper.byteToString(sendBuff));
//            log.info("发送数据成功1");
            // 创建一个新的bytebuffer
            ByteBuffer buffer = ByteBuffer.allocate(sendBuff.length);
            buffer.put(pkt.getFullBuff());
            return buffer;
        } catch (Exception ex) {
            throw new RuntimeException();
        }
    }

    /**
     * 业务处理，根据初步的解析对象，解析具体的数据单元
     *
     * @param packet         初步解析的数据包，不包含具体的数据单元
     * @param channelContext
     * @throws Exception
     */
    @Override
    public void handler(Packet packet, ChannelContext channelContext) throws Exception {
        log.debug("--- 业务处理 ---");
        ModbusPacket pkt = (ModbusPacket) packet;
        List<byte[]> outData = new ArrayList<>();
        byte[] fullBuff = pkt.getFullBuff();
        outData.add(fullBuff);
        /* 收到数据后，推送数据到EventBus */
        SiemensReceiveData siemensReceiveData = new SiemensReceiveData();
        siemensReceiveData.setData_all(ByteHelper.bytesArrayToHexString(fullBuff));
        EventBusCenter.getEventBus().post(siemensReceiveData);
        log.debug("接收数据 " + ByteHelper.byteToString(fullBuff));
    }
}
